﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using Neudesic.Pulse.Client.Tests;
using Neudesic.Pulse.Entities;
using System;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.Linq;

namespace Neudesic.Pulse.Client.Tests
{
    /// <summary>
    /// Summary description for RestResourceClientPostTests
    /// </summary>
    [TestClass]
    public class RestResourceClientPostTests
    {

        private TestContext testContextInstance;
        PulseClient client = new PulseClient(TestHelper.BaseAddress, AuthenticationScheme.Ntlm);

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        [TestMethod]
        [TestCategory("Integration")]
        public void RestResourceClient_AddStatus()
        {

            Entity me = client.CurrentUser;
            StatusRequest entity = new StatusRequest()
            {
                Text = string.Format("Sample unit test message.  {0}", Guid.NewGuid().ToString())
            };

            string location = client.CreateStatus(entity, me); // Post to my activities

            Assert.IsTrue(!string.IsNullOrEmpty(location));

        }

        [TestMethod]
        [TestCategory("Integration")]
        public void RestResourceClient_AddQuestion()
        {

            Entity me = client.CurrentUser;
            StatusRequest entity = new StatusRequest()
            {
                Text = string.Format("What is the answer?  {0}", Guid.NewGuid().ToString())
            };

            string location = client.CreateQuestion(entity, me); // Post to my activities

            Assert.IsTrue(!string.IsNullOrEmpty(location));

        }


        [TestMethod]
        [TestCategory("Integration")]
        public void RestResourceClient_AddImage()
        {

            Entity me = client.CurrentUser;
            byte[] buffer = TestResources.NeudesicLogo.GetBytes(ImageFormat.Png);

            string location = client.Post(buffer, UriUtility.CombineUri(me.Url, "images")); // Post to my images

            Assert.IsTrue(!string.IsNullOrEmpty(location));

            // Add the status so we can delete it later.
            StatusRequest entity = new StatusRequest()
            {
                Text = string.Format("Sample image message.  {0}", Guid.NewGuid().ToString()),
                Link = location
            };

            location = client.Post(entity, me.Feed.Url);
            client.Delete(location);

        }

        [TestMethod]
        [TestCategory("Integration")]
        public void RestResourceClient_AddStatusLike()
        {

            Entity me = client.CurrentUser;

            // Add the status so we can delete it later.
            StatusRequest entity = new StatusRequest()
            {
                Text = string.Format("Sample status message.  {0}", Guid.NewGuid().ToString()),
            };

            string location = client.Post(entity, me.Feed.Url);
            Activity activity = client.GetActivity(location);

            // Add a personal like
            client.CreateLike(activity);

            client.Delete(location);

        }

        [TestMethod]
        [TestCategory("Integration")]
        public void RestResourceClient_AddAnswerLike()
        {

            Entity me = client.CurrentUser;

            StatusRequest entity = new StatusRequest()
            {
                Text = string.Format("What is the answer?  {0}", Guid.NewGuid().ToString())
            };

            var question = client.GetActivity(client.CreateQuestion(entity, me));

            string answer = client.CreateAnswer("42", question);
            Activity answerA = client.GetActivity(answer);

            // Add a like
            client.CreateLike(answerA);

            client.Delete(question.Url);

        }

        [TestMethod]
        [TestCategory("Integration")]
        public void RestResourceClient_AddAnswerComment()
        {

            Entity me = client.CurrentUser;

            StatusRequest entity = new StatusRequest()
            {
                Text = string.Format("What is the answer?  {0}", Guid.NewGuid().ToString())
            };

            var question = client.GetActivity(client.CreateQuestion(entity, me));

            string answer = client.CreateAnswer("42", question);
            Activity answerA = client.GetActivity(answer);

            // Add a like
            client.CreateComment("The truth!", answerA);

            client.Delete(question.Url);

        }

        /// <remarks>
        /// Covers both answer and vote operations.
        /// </remarks>
        [TestMethod]
        [TestCategory("Integration")]
        public void RestResourceClient_AddQuestionAnswer_AndVote()
        {

            Entity me = client.CurrentUser;

            StatusRequest entity = new StatusRequest()
            {
                Text = string.Format("What is the answer?  {0}", Guid.NewGuid().ToString())
            };

            var question = client.GetActivity(client.CreateQuestion(entity, me)); 

            var answer = client.GetActivity(client.CreateAnswer("42", question));

            Assert.IsFalse(string.IsNullOrEmpty(answer.Text));

            client.CreateVote(VoteRequestType.Up, answer);
            client.CreateVote(VoteRequestType.Down, answer);

            client.Delete(question.Url);

        }

        [TestMethod]
        [TestCategory("Integration")]
        public void RestResourceClient_AddStatusComment()
        {

            Entity me = client.CurrentUser;

            // Add the status so we can delete it later.
            StatusRequest entity = new StatusRequest()
            {
                Text = string.Format("Sample status message.  {0}", Guid.NewGuid().ToString()),
            };

            string location = client.Post(entity, me.Feed.Url);
            Activity activity = client.GetActivity(location);

            // Add a status.
            string comment = client.CreateComment("Unit test comment on this status.", activity);

            client.Delete(location);

        }


        [TestMethod]
        [TestCategory("Integration")]
        public void RestResourceClient_AddPage()
        {

            // Create page
            Guid guid = Guid.NewGuid();
            string page = client.CreatePage("Unit test page.", string.Format("Unit test page {0}", guid));

            // Get page
            Entity entity = client.Get<Entity>(page);

            try
            {
                Assert.IsNotNull(entity);
                Assert.IsFalse(string.IsNullOrEmpty(entity.Name));
            }
            finally
            {
                client.DeleteResource(page);
            }

        }

        [TestMethod]
        [TestCategory("Integration")]
        public void RestResourceClient_AddSystem()
        {

            // Create system
            Guid guid = Guid.NewGuid();
            string system = client.CreateSystem(guid.ToString(), string.Format("Unit test system {0}", guid));

            // Get system
            Entity entity = client.Get<Entity>(system);

            Assert.IsNotNull(entity);
            Assert.IsFalse(string.IsNullOrEmpty(entity.Name));

            client.DeleteResource(system);

        }

        [TestMethod]
        [TestCategory("Integration")]
        public void RestResourceClient_AddTag()
        {

            // Create tag
            string tag = "MyTag";
            string location = client.CreateTag(tag);

            try
            {
                Assert.IsFalse(string.IsNullOrEmpty(location));
            }
            finally
            {
                client.DeleteResource(location);
            }

        }

        [TestMethod]
        [TestCategory("Integration")]
        public void RestResourceClient_AddSubscription()
        {

            Entity me = client.CurrentUser;

            // Create page
            Guid guid = Guid.NewGuid();
            string location = client.CreatePage(guid.ToString(), string.Format("Unit test page {0}", guid));

            // Grab the page so we can get the feed uri
            Entity page = client.Get<Entity>(location);

            // Subscribe
            client.CreateSubscription(page, me);

            // Get subscriptions, confirm included
            List<Entity> subscriptions = client.GetSubscriptions(me);

            try
            {
                Assert.IsTrue(subscriptions.Exists((s) => s.Name.Contains(guid.ToString())));
            }
            finally
            {

                // Delete subscription
                client.DeleteSubscription(page, me);

                // Delete page
                client.DeleteResource(location);

            }

        }

        [TestMethod]
        [TestCategory("Integration")]
        public void RestResourceClient_AddAvatar()
        {

            Entity me = client.CurrentUser;
            byte[] buffer = TestResources.NeudesicLogo.GetBytes(ImageFormat.Png);

            client.CreateAvatar(buffer, me);

            // Assume a happy path == success.

        }

        [TestMethod]
        [TestCategory("Integration")]
        public void RestResourceClient_ClearNotifications()
        {

            Entity me = client.CurrentUser;
            client.ClearNotifications(me);

            // Assume a happy path == success.

        }

        [TestMethod]
        [TestCategory("Integration")]
        public void RestResourceClient_UpdatePage()
        {

            // Create page
            Guid guid = Guid.NewGuid();
            string page = client.CreatePage(guid.ToString(), string.Format("Unit test page {0}", guid));

            client.UpdatePage("New name", "New description.", page);

            // Get page
            Entity entity = client.Get<Entity>(page);

            try
            {
                Assert.AreEqual<string>("New name", entity.Name);
            }
            finally
            {
                client.DeleteResource(page);
            }

        }

        [TestMethod]
        [TestCategory("Integration")]
        public void RestResourceClient_UpdateSystem()
        {

            // Create system
            Guid guid = Guid.NewGuid();
            string system = client.CreateSystem(guid.ToString(), string.Format("Unit test system {0}", guid));

            client.UpdateSystem("New name", "New description.", system);

            // Get system
            Entity entity = client.Get<Entity>(system);

            try
            {
                Assert.AreEqual<string>("New name", entity.Name);
            }
            finally
            {
                client.DeleteResource(system);
            }

        }

        [TestMethod]
        [TestCategory("Integration")]
        public void RestResourceClient_AddTagSubscription()
        {

            // Create tag
            string tag = "MyTag79";
            string location = client.CreateTag(tag);
            Entity page = client.Get<Entity>(client.CreatePage("MyPage79", "A unit test page 79."));

            try
            {

                // Create a subscription to a page for this tag.
                client.CreateTagSubscription(tag, page, true);
                
            }
            finally
            {
                client.DeleteResource(page.Url);
                client.DeleteResource(location);
            }

        }

        [TestMethod]
        [TestCategory("Integration")]
        public void RestResourceClient_AddTagActivitySubscription()
        {

            // Create tag
            string tag = "MyTag79";
            string location = client.CreateTag(tag);

            Entity me = client.CurrentUser;

            StatusRequest entity = new StatusRequest()
            {
                Text = string.Format("What is the answer?  {0}", Guid.NewGuid().ToString())
            };

            string question = client.CreateQuestion(entity, me);
            Activity questionE = client.GetActivity(question);

            try
            {

                // Create a subscription to a question for this tag.
                client.CreateTagActivitySubscription(tag, questionE, true);

            }
            finally
            {
                client.DeleteResource(question);
                client.DeleteResource(location);
            }

        }

        [TestMethod]
        [TestCategory("Integration")]
        public void RestResourceClient_AddPhraseTagSubscription()
        {

            // Create tag
            string tag = "MyTag79";
            string tagUri = client.CreateTag(tag);

            Entity me = client.CurrentUser;
            string phrase = "Find me";

            try
            {

                // Create a subscription to a question for this tag.
                client.CreatePhraseTagSubscription(phrase, tag);

            }
            finally
            {
                client.DeleteResource(tagUri);
            }

        }

    }
}
